//===============================================================================
// Microsoft patterns & practices
// Web Client Software Factory
//-------------------------------------------------------------------------------
// Copyright (C) Microsoft Corporation.  All rights reserved.
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY
// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT
// LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
// FITNESS FOR A PARTICULAR PURPOSE.
//-------------------------------------------------------------------------------
// The example companies, organizations, products, domain names,
// e-mail addresses, logos, people, places, and events depicted
// herein are fictitious.  No association with any real company,
// organization, product, domain name, email address, logo, person,
// places, or events is intended or should be inferred.
//===============================================================================
using System;
using WCSFContrib.PageFlow.Xml.Tests.Mocks;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using WCSFContrib.PageFlow;
using System.Collections.Generic;

namespace WCSFContrib.PageFlow.Xml.Tests
{
	[TestClass]
	public class XmlPageFlowFixture
	{
         private static IDictionary<string, NavigationGraph> _navigationGraphs;

        [ClassInitialize]
        public static void SetUp(TestContext testContext)
        {
            _navigationGraphs = new Dictionary<string, NavigationGraph>();
            NavigationGraph navigationGraphUnconstrained = new MockUnconstrainedXmlPageFlowNavigationGraph();
            NavigationGraph navigationGraphConstrained = new MockConstrainedXmlPageFlowNavigationGraph();
            NavigationGraph navigationGraphWithCondition = new MockUnconstrainedXmlPageFlowNavigationGraph2();

            _navigationGraphs.Add(navigationGraphUnconstrained.PageFlowType.AssemblyQualifiedName, navigationGraphUnconstrained);
            _navigationGraphs.Add(navigationGraphConstrained.PageFlowType.AssemblyQualifiedName, navigationGraphConstrained);
            _navigationGraphs.Add(navigationGraphWithCondition.PageFlowType.AssemblyQualifiedName, navigationGraphWithCondition);

        }

        [TestMethod]
        public void CanGetNameAndId()
        {
            using (XmlPageFlowFactory factory = new XmlPageFlowFactory(_navigationGraphs, new MockNavigationService()))
            {
                IPageFlow pageFlow = factory.GetPageFlow(typeof(MockUnconstrainedPageFlow));

                Assert.AreNotEqual(Guid.Empty, pageFlow.Id);
                Assert.IsNotNull(pageFlow.Definition.Name);
                Assert.AreEqual("Unconstrained", pageFlow.Definition.Name);
            }
        }

        [TestMethod]
        public void CanEnumeratePages()
        {
            using (XmlPageFlowFactory factory = new XmlPageFlowFactory(_navigationGraphs, new MockNavigationService()))
            {
                IPageFlow pageFlow = factory.GetPageFlow(typeof(MockUnconstrainedPageFlow));

                Assert.IsTrue(pageFlow.Definition.Pages.Contains(new Page("pageA", "~/pageA.aspx")));
                Assert.IsFalse(pageFlow.Definition.Pages.Contains(new Page("pageZ", "~/pageA.aspx")));
            }
        }

        [TestMethod]
        public void CanGetCurrentPage()
        {
            using (XmlPageFlowFactory factory = new XmlPageFlowFactory(_navigationGraphs, new MockNavigationService()))
            {
                IPageFlow pageFlow = factory.GetPageFlow(typeof(MockUnconstrainedPageFlow));
                pageFlow.Start();
                Assert.IsNotNull(pageFlow.CurrentPage);
            }
        }

        [TestMethod]
        public void OnStartGoesToCurrentPage()
        {
            using (XmlPageFlowFactory factory = new XmlPageFlowFactory(_navigationGraphs, new MockNavigationService()))
            {
                IPageFlow pageFlow = factory.GetPageFlow(typeof(MockUnconstrainedPageFlow));
            
                pageFlow.Start();

                Assert.AreEqual("pageA", pageFlow.Definition.StartPage.Name);
                Assert.AreEqual("pageA", pageFlow.CurrentPage.Name);
            }
        }

        [TestMethod]
        public void CanRedirectToCurrentPageInUnconstrainedPageFlowIsTrue()
        {
            using (XmlPageFlowFactory factory = new XmlPageFlowFactory(_navigationGraphs, new MockNavigationService()))
            {
                IPageFlow pageFlow = factory.GetPageFlow(typeof(MockUnconstrainedPageFlow));
   
                pageFlow.Start();

                Assert.IsTrue(pageFlow.CanRedirectTo(pageFlow.CurrentPage.Name));
            }
        }

        [TestMethod]
        public void CanRedirectToCurrentPageInConstrainedPageFlowIsTrue()
        {
            using (XmlPageFlowFactory factory = new XmlPageFlowFactory(_navigationGraphs, new MockNavigationService()))
            {
                IPageFlow pageFlow = factory.GetPageFlow(typeof(MockConstrainedPageFlow));
   
                pageFlow.Start();

                Assert.IsTrue(pageFlow.CanRedirectTo(pageFlow.CurrentPage.Name));
            }
        }

        [TestMethod]
        public void UnconstraintedPageFlowSendsUserBackJumping()
        {
            Assert.IsTrue(true);
        }

        [TestMethod]
        public void RedirectToCurrentPageInConstrainedPageFlowDoesNotChangeCurrentPage()
        {
            using (XmlPageFlowFactory factory = new XmlPageFlowFactory(_navigationGraphs, new MockNavigationService()))
            {
                IPageFlow pageFlow = factory.GetPageFlow(typeof(MockConstrainedPageFlow));
   
                pageFlow.Start();

                string originalPage = pageFlow.CurrentPage.Name;
                pageFlow.SetCurrentPage(pageFlow.CurrentPage.Name);
                Assert.AreEqual(originalPage, pageFlow.CurrentPage.Name);
            }
        }

        [TestMethod]
        public void RedirectToCurrentPageInUnconstrainedPageFlowDoesNotChangeCurrentPage()
        {
            using (XmlPageFlowFactory factory = new XmlPageFlowFactory(_navigationGraphs, new MockNavigationService()))
            {
                IPageFlow pageFlow = factory.GetPageFlow(typeof(MockUnconstrainedPageFlow));
   
                pageFlow.Start();

                string originalPage = pageFlow.CurrentPage.Name;
                pageFlow.SetCurrentPage(pageFlow.CurrentPage.Name);
                Assert.AreEqual(originalPage, pageFlow.CurrentPage.Name);
            }
        }

        [TestMethod]
        [ExpectedException(typeof(NavigationException))]
        public void RedirectToAnotherPageInConstrainedPageFlowThrows()
        {
            using (XmlPageFlowFactory factory = new XmlPageFlowFactory(_navigationGraphs, new MockNavigationService()))
            {
                IPageFlow pageFlow = factory.GetPageFlow(typeof(MockConstrainedPageFlow));
   
                pageFlow.Start();

                Assert.IsTrue(pageFlow.Definition.ContainsPage(new Page("pageB", "~/pageB.aspx")));
                pageFlow.SetCurrentPage("pageB");
            }
        }

        [TestMethod]
        [ExpectedException(typeof(NavigationException))]
        public void RedirectToNonExistingPageInConstrainedPageFlowThrows()
        {
            using (XmlPageFlowFactory factory = new XmlPageFlowFactory(_navigationGraphs, new MockNavigationService()))
            {
                IPageFlow pageFlow = factory.GetPageFlow(typeof(MockConstrainedPageFlow));

                pageFlow.Start();

                Assert.IsFalse(pageFlow.Definition.ContainsPage(new Page("elsewhere", "elsewhere.aspx")));

                pageFlow.SetCurrentPage("elsewhere");
            }
        }

        [TestMethod]
        public void RedirectToAnotherPageInUnconstrainedPageFlowChangesCurrentPageToTarget()
        {
            using (XmlPageFlowFactory factory = new XmlPageFlowFactory(_navigationGraphs, new MockNavigationService()))
            {
                IPageFlow pageFlow = factory.GetPageFlow(typeof(MockUnconstrainedPageFlow));
   
                pageFlow.Start();
                pageFlow.SetCurrentPage("pageB");

                Assert.AreEqual("pageB", pageFlow.CurrentPage.Name);
            }
        }

        [TestMethod]
        public void ShouldDeletePageFlowInstanceAndRedirectToCancelUrlOnTerminate()
        {
            MockNavigationService navigationService = new MockNavigationService();
            using (XmlPageFlowFactory factory = new XmlPageFlowFactory(_navigationGraphs, navigationService))
            {
                IPageFlow pageFlow = factory.GetPageFlow(typeof(MockUnconstrainedPageFlow));
   
                pageFlow.Start();
                pageFlow.Abort(true);

                Assert.AreEqual(pageFlow.Definition.AbortPage, navigationService.LastRequestedPage);
            }
        }

        [TestMethod]
        public void PageflowShouldCleanUpOnAbort()
        {
            MockNavigationService navigationService = new MockNavigationService();

            using (XmlPageFlowFactory factory = new XmlPageFlowFactory(_navigationGraphs, navigationService))
            {
                IPageFlow pageFlow = factory.GetPageFlow(typeof(MockUnconstrainedPageFlow));
                Guid id = pageFlow.Id;

                pageFlow.Start();
                pageFlow.Abort(true);

                try
                {
                    XmlPageFlow pf = (XmlPageFlow)factory.GetPageFlow(typeof(MockUnconstrainedPageFlow), id);

                    Assert.AreEqual(PageFlowStatus.Terminated, pf.Status);
                }
                catch (PageFlowException ex)
                {
                    Assert.IsTrue(ex.Message.Contains(id.ToString()));
                    return;
                }

                Assert.Fail("Wrong exception or no exception thrown");
            }
        }

        [TestMethod]
        public void ShouldDeletePageFlowInstanceAndNotRedirectToCancelUrlOnTerminate()
        {
            MockNavigationService navigationService = new MockNavigationService();

            using (XmlPageFlowFactory factory = new XmlPageFlowFactory(_navigationGraphs, navigationService))
            {
                IPageFlow pageFlow = factory.GetPageFlow(typeof(MockUnconstrainedPageFlow));
                pageFlow.Start();

                navigationService.LastRequestedPage = null;

                pageFlow.Abort(false);

                Assert.IsNull(navigationService.LastRequestedPage);
            }
        }

        [TestMethod]
        public void CanQueryPageFlowStatus()
        {
            MockNavigationService navigationService = new MockNavigationService();

            using (XmlPageFlowFactory factory = new XmlPageFlowFactory(_navigationGraphs, navigationService))
             {
                IPageFlow pageFlow = factory.GetPageFlow(typeof(MockUnconstrainedPageFlow));
                Assert.AreEqual(PageFlowStatus.NotStarted, pageFlow.Status);

                pageFlow.Start();
                Assert.AreEqual(PageFlowStatus.Running, pageFlow.Status);

                pageFlow.Abort(false);
                Assert.AreEqual(PageFlowStatus.Terminated, pageFlow.Status);
            }
        }

        [TestMethod]
        public void ShouldExposeXmlInstance()
        {
            MockNavigationService navigationService = new MockNavigationService();

            using (XmlPageFlowFactory factory = new XmlPageFlowFactory(_navigationGraphs, navigationService))
            {
                XmlPageFlow pageFlow = (XmlPageFlow)factory.GetPageFlow(typeof(MockUnconstrainedPageFlow));

                Assert.IsNotNull(pageFlow.Instance);
                Assert.IsTrue(pageFlow.Instance is XmlPageFlowInstance);
            }
        }

        [TestMethod]
        public void ShouldRedirectToCurrentPage()
        {
            MockNavigationService navigationService = new MockNavigationService();

            using (XmlPageFlowFactory factory = new XmlPageFlowFactory(_navigationGraphs, navigationService))
            {
                IPageFlow pageFlow = factory.GetPageFlow(typeof(MockUnconstrainedPageFlow));
                pageFlow.Start();
                navigationService.LastRequestedPage = null;
                pageFlow.RedirectToCurrentPage();

                Assert.AreEqual(pageFlow.CurrentPage, navigationService.LastRequestedPage);
            }
        }

        [TestMethod]
        public void CanQueryPagesOnPageFlow()
        {
            MockNavigationService navigationService = new MockNavigationService();

            using (XmlPageFlowFactory factory = new XmlPageFlowFactory(_navigationGraphs, navigationService))
            {
                IPageFlow pageFlow = factory.GetPageFlow(typeof(MockUnconstrainedPageFlow));

                Assert.AreEqual(pageFlow.Definition.Pages[0].Name, "pageA");
                Assert.AreEqual(pageFlow.Definition.Pages.Count,
                                Activator.CreateInstance<MockUnconstrainedXmlPageFlowNavigationGraph>().Views.Count);
            }
        }

        [TestMethod]
        public void CanQueryStartPage()
        {
            MockNavigationService navigationService = new MockNavigationService();
            using (XmlPageFlowFactory factory = new XmlPageFlowFactory(_navigationGraphs, navigationService))
            {
                IPageFlow pageFlow = factory.GetPageFlow(typeof(MockUnconstrainedPageFlow));

                Assert.IsNotNull(pageFlow.Definition.StartPage.Name,
                                 Activator.CreateInstance<MockUnconstrainedXmlPageFlowNavigationGraph>().StartView.Name);
            }
        }

        [TestMethod]
        public void UserCanQueryAboutPosibleTransitionsOnPageFlow()
        {
            MockNavigationService navigationService = new MockNavigationService();

            using (XmlPageFlowFactory factory = new XmlPageFlowFactory(_navigationGraphs, navigationService))
            {
                IPageFlow pageFlow = factory.GetPageFlow(typeof(MockUnconstrainedPageFlow));
                pageFlow.Start();
                Assert.AreEqual(1, pageFlow.Transitions.Count);
                Assert.IsNotNull(pageFlow.Transitions[0]);
            }
        }

        [TestMethod]
        public void PageFlowFiresStartedEventOnStart()
        {
            MockNavigationService navigationService = new MockNavigationService();

            using (XmlPageFlowFactory factory = new XmlPageFlowFactory(_navigationGraphs, navigationService))
            {
                IPageFlow pageFlow = factory.GetPageFlow(typeof(MockUnconstrainedPageFlow));
                TestHandler<PageFlowEventArgs> handler = new TestHandler<PageFlowEventArgs>();
                pageFlow.Started += new EventHandler<PageFlowEventArgs>(handler.HandleEvent);
                pageFlow.Start();

                Assert.AreEqual(handler.EventArgs.PageFlow, pageFlow);
                Assert.AreEqual(1, handler.FireCount);
            }
        }

        [TestMethod]
        public void PageFlowFiresAbortedEventOnStart()
        {
            MockNavigationService navigationService = new MockNavigationService();

            using (XmlPageFlowFactory factory = new XmlPageFlowFactory(_navigationGraphs, navigationService))
            {
                IPageFlow pageFlow = factory.GetPageFlow(typeof(MockUnconstrainedPageFlow));
                TestHandler<PageFlowAbortedEventArgs> handler = new TestHandler<PageFlowAbortedEventArgs>();
                pageFlow.Aborted += new EventHandler<PageFlowAbortedEventArgs>(handler.HandleEvent);
                pageFlow.Start();
                pageFlow.Abort(false);

                Assert.AreEqual(handler.EventArgs.AbortedPageFlowId, pageFlow.Id);
                Assert.AreEqual(1, handler.FireCount);
            }
        }

        [TestMethod]
        public void ShouldGetPageFlowDeclaringType()
        {
            using (XmlPageFlowFactory factory = new XmlPageFlowFactory(_navigationGraphs, new MockNavigationService()))
            {
                IPageFlow pageFlow = factory.GetPageFlow(typeof(MockUnconstrainedPageFlow));

                Assert.AreEqual(typeof(MockUnconstrainedPageFlow), pageFlow.Definition.PageFlowType);
            }
        }

        [TestMethod]
        public void ShouldPassDataToPageFlowAndViceversa()
        {
            using (XmlPageFlowFactory factory = new XmlPageFlowFactory(_navigationGraphs, new MockNavigationService()))
            {
                IPageFlow pageFlow = factory.GetPageFlow(typeof(MockUnconstrainedPageFlow));

                pageFlow.Start();
                pageFlow.UserData["myPageFlowData"] = 1;

                Assert.IsNotNull(pageFlow.UserData["myPageFlowData"]);
                Assert.AreEqual(1, pageFlow.UserData["myPageFlowData"]);
            }
        }


        [TestMethod]
        public void ShouldDisposeUserData()
        {
            using (XmlPageFlowFactory factory = new XmlPageFlowFactory(_navigationGraphs, new MockNavigationService()))
            {
                IPageFlow pageFlow = factory.GetPageFlow(typeof(MockUnconstrainedPageFlow));

                pageFlow.Start();
                pageFlow.UserData["myPageFlowData"] = 1;
                pageFlow.UserData.Remove("myPageFlowData");
                Assert.IsFalse(pageFlow.UserData.Contains("myPageFlowData"));
            }
        }

        [TestMethod]
        [ExpectedException(typeof(ArgumentException))]
        public void ShouldThrowIfNotExists()
        {
            using (XmlPageFlowFactory factory = new XmlPageFlowFactory(_navigationGraphs, new MockNavigationService()))
            {
                IPageFlow pageFlow = factory.GetPageFlow(typeof(MockUnconstrainedPageFlow));

                pageFlow.Start();

                string value = (string)pageFlow.UserData["notExistingSlot"];
                Assert.IsNull(value);
            }
        }

        [TestMethod]
        public void ShouldReturnKeys()
        {
            using (XmlPageFlowFactory factory = new XmlPageFlowFactory(_navigationGraphs, new MockNavigationService()))
            {
                IPageFlow pageFlow = factory.GetPageFlow(typeof(MockUnconstrainedPageFlow));

                pageFlow.Start();

                int initialCount = pageFlow.UserData.Keys.Count;

                pageFlow.UserData["a"] = 0;
                pageFlow.UserData["b"] = 0;
                pageFlow.UserData["c"] = 0;

                Assert.AreEqual(initialCount + 3, pageFlow.UserData.Keys.Count);
            }
        }

        [TestMethod]
        public void ShouldTestWhetherContainsStateSlot()
        {
            using (XmlPageFlowFactory factory = new XmlPageFlowFactory(_navigationGraphs, new MockNavigationService()))
            {
                IPageFlow pageFlow = factory.GetPageFlow(typeof(MockUnconstrainedPageFlow));

                pageFlow.Start();

                pageFlow.UserData["MockSlot01"] = 0;

                Assert.IsTrue(pageFlow.UserData.Contains("MockSlot01"));
                Assert.IsFalse(pageFlow.UserData.Contains("MockSlot02"));
            }
        }

        [TestMethod]
        [ExpectedException(typeof(ArgumentNullException))]
        public void SetStateSlotKeyCannotBeNullOrEmpty()
        {
            using (XmlPageFlowFactory factory = new XmlPageFlowFactory(_navigationGraphs, new MockNavigationService()))
            {
                IPageFlow pageFlow = factory.GetPageFlow(typeof(MockUnconstrainedPageFlow));

                pageFlow.Start();

                pageFlow.UserData[string.Empty] = 0;
            }
        }

        [TestMethod]
        [ExpectedException(typeof(ArgumentNullException))]
        public void GetStateSlotKeyCannotBeNullOrEmpty()
        {
            using (XmlPageFlowFactory factory = new XmlPageFlowFactory(_navigationGraphs, new MockNavigationService()))
            {
                IPageFlow pageFlow = factory.GetPageFlow(typeof(MockUnconstrainedPageFlow));

                pageFlow.Start();

                object value = pageFlow.UserData[string.Empty];

                Assert.IsNull(value);
            }
        }

        [TestMethod]
        [ExpectedException(typeof(ArgumentNullException))]
        public void ContainsStateSlotKeyCannotBeNullOrEmpty()
        {
            using (XmlPageFlowFactory factory = new XmlPageFlowFactory(_navigationGraphs, new MockNavigationService()))
            {
                IPageFlow pageFlow = factory.GetPageFlow(typeof(MockUnconstrainedPageFlow));

                pageFlow.Start();

                pageFlow.UserData.Contains(null);
            }
        }

        [TestMethod]
        [ExpectedException(typeof(ArgumentNullException))]
        public void RemoveStateSlotKeyCannotBeNullOrEmpty()
        {
            using (XmlPageFlowFactory factory = new XmlPageFlowFactory(_navigationGraphs, new MockNavigationService()))
            {
                IPageFlow pageFlow = factory.GetPageFlow(typeof(MockUnconstrainedPageFlow));

                pageFlow.Start();

                pageFlow.UserData.Remove(string.Empty);
            }
        }

        [TestMethod]
        public void ShouldCanRedirectToBeFalseIfPageFlowIsConstrainedAndCurrentPageIsDiffrentFromRequestedOne()
        {
            using (XmlPageFlowFactory factory = new XmlPageFlowFactory(_navigationGraphs, new MockNavigationService()))
            {
                IPageFlow pageFlow = factory.GetPageFlow(typeof(MockConstrainedPageFlow));

                pageFlow.Start();
                bool canRedirect = pageFlow.CanRedirectTo("pageB");

                Assert.IsFalse(canRedirect);
            }
        }

        [TestMethod]
        public void ShouldCanRedirectToBeTrueIfPageFlowIsUnconstrainedAndCurrentPageIsDiffrentFromRequestedOne()
        {
            using (XmlPageFlowFactory factory = new XmlPageFlowFactory(_navigationGraphs, new MockNavigationService()))
            {
                IPageFlow pageFlow = factory.GetPageFlow(typeof(MockUnconstrainedPageFlow));

                pageFlow.Start();
                bool canRedirect = pageFlow.CanRedirectTo("pageB");

                Assert.IsTrue(canRedirect);
            }
        }

        [TestMethod]
        public void DataIsNotSharedAcrossInstances()
        {
            using (XmlPageFlowFactory factory = new XmlPageFlowFactory(_navigationGraphs, new MockNavigationService()))
            {
                IPageFlow pageFlow1 = factory.GetPageFlow(typeof(MockUnconstrainedPageFlow));

                pageFlow1.Start();
                pageFlow1.UserData["CustomerStatus"] = "green";

                IPageFlow pageFlow2 = factory.GetPageFlow(typeof(MockUnconstrainedPageFlow));
                pageFlow2.Start();

                Assert.IsNotNull(pageFlow1.UserData["CustomerStatus"]);
                Assert.AreEqual("green", pageFlow1.UserData["CustomerStatus"]);
                Assert.IsFalse(pageFlow2.UserData.Contains("CustomerStatus"));
            }
        }

        [TestMethod]
        public void DevCanSuspendPageFlow()
        {
            using (XmlPageFlowFactory factory = new XmlPageFlowFactory(_navigationGraphs, new MockNavigationService()))
            {
                IPageFlow pageFlow = factory.GetPageFlow(typeof(MockUnconstrainedPageFlow));

                pageFlow.Start();
                pageFlow.Suspend();

                Assert.AreEqual(PageFlowStatus.Suspended, pageFlow.Status);
            }
        }

        [TestMethod]
        public void DevCanResumePageFlow()
        {
            using (XmlPageFlowFactory factory = new XmlPageFlowFactory(_navigationGraphs, new MockNavigationService()))
            {
                IPageFlow pageFlow = factory.GetPageFlow(typeof(MockUnconstrainedPageFlow));
                pageFlow.Start();
                pageFlow.Suspend();
                pageFlow.Resume();

                Assert.AreEqual(PageFlowStatus.Running, pageFlow.Status);
            }
        }

        [TestMethod]
        public void PageFlowFiresSuspendedEventOnSuspend()
        {
            using (XmlPageFlowFactory factory = new XmlPageFlowFactory(_navigationGraphs, new MockNavigationService()))
            {
                IPageFlow pageFlow = factory.GetPageFlow(typeof(MockUnconstrainedPageFlow));
                pageFlow.Start();
                TestHandler<PageFlowEventArgs> handler = new TestHandler<PageFlowEventArgs>();
                pageFlow.Suspended += new EventHandler<PageFlowEventArgs>(handler.HandleEvent);
                pageFlow.Suspend();

                Assert.AreEqual(1, handler.FireCount);
                Assert.AreEqual(pageFlow, handler.EventArgs.PageFlow);
            }
        }

        [TestMethod]
        public void PageFlowFiresResumedEventOnResume()
        {
            using (XmlPageFlowFactory factory = new XmlPageFlowFactory(_navigationGraphs, new MockNavigationService()))
            {
                IPageFlow pageFlow = factory.GetPageFlow(typeof(MockUnconstrainedPageFlow));
                pageFlow.Start();
                pageFlow.Suspend();
                TestHandler<PageFlowEventArgs> handler = new TestHandler<PageFlowEventArgs>();
                pageFlow.Resumed += new EventHandler<PageFlowEventArgs>(handler.HandleEvent);
                pageFlow.Resume();

                Assert.AreEqual(1, handler.FireCount);
                Assert.AreEqual(pageFlow, handler.EventArgs.PageFlow);
            }
        }

        [TestMethod]
        public void ShouldNotRedirectUserWhenSuspending()
        {
            MockNavigationService navigationService = new MockNavigationService();
            using (XmlPageFlowFactory factory = new XmlPageFlowFactory(_navigationGraphs, new MockNavigationService()))
            {
                IPageFlow pageFlow = factory.GetPageFlow(typeof(MockUnconstrainedPageFlow));
                pageFlow.Start();

                //clear the navigation
                navigationService.LastRequestedPage = null;

                pageFlow.Suspend();

                Assert.IsNull(navigationService.LastRequestedPage);
            }
        }

        [TestMethod]
        public void ShouldKeepStateWhenSuspendingAndResuming()
        {
            Guid pageFlowId;
            Page preSuspendPage;
            using (XmlPageFlowFactory factory = new XmlPageFlowFactory(_navigationGraphs, new MockNavigationService()))
            {
                IPageFlow pageFlow = factory.GetPageFlow(typeof(MockUnconstrainedPageFlow));
                pageFlow.Start();
                pageFlowId = pageFlow.Id;
                pageFlow.UserData["something"] = 1;
                pageFlow.Navigate("goToPageB");
                preSuspendPage = pageFlow.CurrentPage;
                pageFlow.Suspend();
            }

            using (XmlPageFlowFactory factory = new XmlPageFlowFactory(_navigationGraphs, new MockNavigationService()))
            {
                IPageFlow pageFlow = factory.GetPageFlow(typeof(MockUnconstrainedPageFlow), pageFlowId);
                pageFlow.Resume();

                Assert.AreEqual(preSuspendPage, pageFlow.CurrentPage);
                Assert.AreEqual(1, pageFlow.UserData["something"]);
                Assert.AreEqual(PageFlowStatus.Running, pageFlow.Status);
            }
        }

        [TestMethod]
        public void ShouldReplaceExisitingSlotWithNewData()
        {
            using (XmlPageFlowFactory factory = new XmlPageFlowFactory(_navigationGraphs, new MockNavigationService()))
            {
                IPageFlow pageFlow = factory.GetPageFlow(typeof(MockUnconstrainedPageFlow));

                pageFlow.Start();

                pageFlow.UserData["slot"] = 1;
                pageFlow.UserData["slot"] = 5;

                Assert.AreEqual(5, (int)pageFlow.UserData["slot"]);
            }
        }

        [TestMethod]
        [ExpectedException(typeof(ArgumentNullException))]
        public void WorkflowInstanceCannotBeNull()
        {
            new XmlPageFlow(null, new MockNavigationService(), null);
        }

        [TestMethod]
        public void ShouldExecuteNamedTransitions()
        {
            using (XmlPageFlowFactory factory = new XmlPageFlowFactory(_navigationGraphs, new MockNavigationService()))
            {
                IPageFlow pageFlow = factory.GetPageFlow(typeof(MockConstrainedPageFlow));

                pageFlow.Start();
                pageFlow.Navigate("goToPageB");
                Assert.AreEqual("pageB", pageFlow.CurrentPage.Name);
            }
        }

        [TestMethod]
        public void NamedTransitionsShouldBeCaseInsensitive()
        {
            using (XmlPageFlowFactory factory = new XmlPageFlowFactory(_navigationGraphs, new MockNavigationService()))
            {
                IPageFlow pageFlow = factory.GetPageFlow(typeof(MockConstrainedPageFlow));

                pageFlow.Start();
                pageFlow.Navigate("gotopAgeb");
                Assert.AreEqual("pageB", pageFlow.CurrentPage.Name);
            }
        }

        [TestMethod]
        public void ShouldExecuteDefaultTransitions()
        {
            using (XmlPageFlowFactory factory = new XmlPageFlowFactory(_navigationGraphs, new MockNavigationService()))
            {
                IPageFlow pageFlow = factory.GetPageFlow(typeof(MockUnconstrainedPageFlow));
                pageFlow.Start();
                pageFlow.Next();

                Assert.AreEqual("pageB", pageFlow.CurrentPage.Name);
            }
        }


        [TestMethod]
        [ExpectedException(typeof(NavigationException))]
        public void ShouldThrowNavigationExceptionIsTransitionDoesntExists()
        {
            using (XmlPageFlowFactory factory = new XmlPageFlowFactory(_navigationGraphs, new MockNavigationService()))
            {
                IPageFlow pageFlow = factory.GetPageFlow(typeof(MockUnconstrainedPageFlow));
                pageFlow.Start();
                pageFlow.Navigate("nonExistingTransition");
            }
        }

        [TestMethod]
        public void ShouldMarkPageFlowAsNotRunningAndFireCompletedEvent()
        {
            using (XmlPageFlowFactory factory = new XmlPageFlowFactory(_navigationGraphs, new MockNavigationService()))
            {
                IPageFlow pageFlow = factory.GetPageFlow(typeof(MockUnconstrainedPageFlow));
                pageFlow.Start();
                TestHandler<PageFlowEventArgs> handler = new TestHandler<PageFlowEventArgs>();
                pageFlow.Completed += new EventHandler<PageFlowEventArgs>(handler.HandleEvent);
                pageFlow.Complete();


                Assert.AreEqual(1, handler.FireCount);
                Assert.AreEqual(pageFlow, handler.EventArgs.PageFlow);
                Assert.AreEqual(PageFlowStatus.Terminated, pageFlow.Status);
            }
        }

        [TestMethod]
        public void MantainStatusWhenCreatingSamePageFlowInDifferentRequests()
        {
            using (XmlPageFlowFactory factory = new XmlPageFlowFactory(_navigationGraphs, new MockNavigationService()))
            {
                // 1st request
                IPageFlow pageFlow = factory.GetPageFlow(typeof(MockUnconstrainedPageFlow));
                pageFlow.Start();
                pageFlow.Suspend();

                Assert.AreEqual(PageFlowStatus.Suspended, pageFlow.Status);

                // 2nd request
                IPageFlow pageFlow2 = factory.GetPageFlow(typeof(MockUnconstrainedPageFlow), pageFlow.Id);

                Assert.AreEqual(PageFlowStatus.Suspended, pageFlow2.Status);
            }
        }

        [TestMethod]
        public void MantainStatusWhenCreatingSamePageFlowInDifferentRequests2()
        {
            using (XmlPageFlowFactory factory = new XmlPageFlowFactory(_navigationGraphs, new MockNavigationService()))
            {
                // 1st request
                IPageFlow pageFlow = factory.GetPageFlow(typeof(MockUnconstrainedPageFlow));

                Assert.AreEqual(PageFlowStatus.NotStarted, pageFlow.Status);

                // 2nd request
                IPageFlow pageFlow2 = factory.GetPageFlow(typeof(MockUnconstrainedPageFlow), pageFlow.Id);
                pageFlow2.Start();

                Assert.AreEqual(PageFlowStatus.Running, pageFlow2.Status);
            }
        }

        [TestMethod]
        [ExpectedException(typeof(PageFlowException))]
        public void SuspendBeforeStartThrows()
        {
            using (XmlPageFlowFactory factory = new XmlPageFlowFactory(_navigationGraphs, new MockNavigationService()))
            {
                IPageFlow pageFlow = factory.GetPageFlow(typeof(MockUnconstrainedPageFlow));
                pageFlow.Suspend();
            }
        }

        [TestMethod]
        [ExpectedException(typeof(PageFlowException))]
        public void ResumeBeforeStartThrows()
        {
            using (XmlPageFlowFactory factory = new XmlPageFlowFactory(_navigationGraphs, new MockNavigationService()))
            {
                IPageFlow pageFlow = factory.GetPageFlow(typeof(MockUnconstrainedPageFlow));
                pageFlow.Resume();
            }
        }

        [TestMethod]
        [ExpectedException(typeof(PageFlowException))]
        public void AbortBeforeStartThrows()
        {
            using (XmlPageFlowFactory factory = new XmlPageFlowFactory(_navigationGraphs, new MockNavigationService()))
            {
                IPageFlow pageFlow = factory.GetPageFlow(typeof(MockUnconstrainedPageFlow));
                pageFlow.Abort(false);
            }
        }

        [TestMethod]
        public void NavigateCallsRedirectOnService()
        {
            MockNavigationService navigationService = new MockNavigationService();
            using (XmlPageFlowFactory factory = new XmlPageFlowFactory(_navigationGraphs, navigationService))
            {
                IPageFlow pageFlow = factory.GetPageFlow(typeof(MockUnconstrainedPageFlow));
                pageFlow.Start();
                pageFlow.Navigate("goToPageB");
                Assert.AreEqual("pageB", navigationService.LastRequestedPage.Name);
            }
        }

        [TestMethod]
        public void ShouldNavigateWithCondition()
        {
            using (XmlPageFlowFactory factory = new XmlPageFlowFactory(_navigationGraphs, new MockNavigationService()))
            {
                IPageFlow pageFlow = factory.GetPageFlow(typeof(MockUnconstrainedPageFlow2));
                pageFlow.Start();

                pageFlow.Navigate("goToPageHWithCondition");
                Assert.AreEqual("pageH", pageFlow.CurrentPage.Name);
            }
        }

        [TestMethod]
        [ExpectedException(typeof(ArgumentNullException))]
        public void ShouldFailOnUncheckedConditionCauseViewIsNull()
        {
            using (XmlPageFlowFactory factory = new XmlPageFlowFactory(_navigationGraphs, new MockNavigationService()))
            {
                IPageFlow pageFlow = factory.GetPageFlow(typeof(MockUnconstrainedPageFlow2));
                pageFlow.Start();

                pageFlow.Navigate("goToNonCheckedCondition");
            }
        } 
	}
}
